<template>
  <div class="home">
    <!-- 使用topology组件 -->
    <topology
      :configs="topologyConfigs"
      :materials="materials"
      :user="user"
      :data="data"
      @event="onEvent"
    ></topology>

    <popupYK ref="yk"></popupYK>
    <popupYT ref="yt"></popupYT>
  </div>
</template>

<script lang="ts">
import popupYK from './DlgYk.vue';
import popupYT from './DlgYt.vue';
import { Component, Vue, Watch } from 'vue-property-decorator';
// 导入topology-vue组件
import topology from 'topology-vue';
// 需要导入topology-vue.css
import 'topology-vue/topology-vue.css';
import Mqtt, { QoS } from 'mqtt';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

//import { Button, Form, FormItem, Input, Message } from 'element-ui'
import {
  defalutMaterials,
  defalutMaterialTabs,
  iconMenus,
  userMenus,
} from './data';
import axios from 'axios';
import globalParam from '@/components/globalParam';

Vue.use(topology);
Vue.use(ElementUI);
Vue.prototype.$message = ElementUI.Message;
Vue.prototype.$notify = ElementUI.Notification;

declare const window: any;

@Component({
  components: {
    popupYK,
    popupYT,
  },
})
export default class Home extends Vue {
  data: any = {
    websocket: '',
    mqttUrl: '',
    component: !!this.$route.query.component,
  };

  topologyConfigs = {
    license: {
      // key: '75628',
      // value: '248848H84848h8H8e8h8H8JAa8H868D8e8H8D8e8e8i8M8H8MAo',
      // version: '16AJAjAG',
      key: '54600',
      value: '248r4rHr4rer3rIr4r3rHrjBarHrirJrer8rJrIrMrhrIrerIBo',
      version: '16BiBNBE',
    },
    logo: null,
    // {
    //   img: 'http://topology.le5le.com/assets/img/favicon.ico',
    //   url: 'http://topology.le5le.com',
    //   target: '_blank',
    //   text: 'le5le',
    // },
    menus: iconMenus,
    loginUrl: 'https://account.le5le.com',
    signupUrl: 'https://account.le5le.com',
    userMenus: userMenus,
    materialTabs: defalutMaterialTabs,
    dataOptionsFn: (pen: any, key: string, value: string) => {
      // pen - 当前画笔对象
      // key - 表单输入左侧的属性名
      // value - 仅下拉搜索时有效，当前输入文本
      console.log('dataOptionsFn', pen, key, value);
      // ************
      // 根据实际业务场景 + 参数返回数组对象。
      // Do sth.
      // ************
      console.log(pen);

      const keys = [{ value: 'aaa', label: '1' }];
      const values = [{ value: '000', label: '1' }];
      return {
        keys,
        // value: true, // 可配置，部门情况可能出现类型报错
        values,
      };
    },
    // locale: 'zh',
  };

  user: any = {
    username: 'le5le',
  };

  materials: any = {
    topology: [],
    system: [],
    uploadHeaders: {
      Authorization: 'your token',
    },
    //uploadFn: this.uploadFunc,
    uploadUrl: '/api/save/image',
  };

  mqttClient: any;
  ctrlMsg: any;

  constructor() {
    super();
    this.ctrlMsg = {};
  }

  @Watch('$route')
  routerChanged() {
    this.created();
  }

  async created() {
    //alert('created');
    const data = (window as any).topologyData;
    // 预览页返回，存在缓存数据
    if (data) {
      this.data = Object.assign({}, data);
      setTimeout(() => {
        (window as any).topologyData = null;
      }, 200);
    } else {
    }

    this.getMaterials();
    this.initMqtt();
  }

  registerBuiness() {
    if (window.registerTools) {
      window.registerTools();
    }

    if (window.registerIot) {
      window.registerIot(this.topologyConfigs.license);
    }
  }

  decodeIcon(data: any) {
    if (data.hasOwnProperty('icon_encode')) {
      data.icon = decodeURI(data.icon_encode);
    }

    if (data.hasOwnProperty('children')) {
      for (var i = 0; i < data.children.length; i++) {
        this.decodeIcon(data.children[i]);
      }
    }
    if (data.hasOwnProperty('pens')) {
      for (var i = 0; i < data.pens.length; i++) {
        this.decodeIcon(data.pens[i]);
      }
    }
  }

  encodeIcon(data: any) {
    if (data.hasOwnProperty('icon')) {
      if (data.icon.length > 0) {
        var s = encodeURI(data.icon);
        data.icon_encode = s;
      }
    }
    if (data.hasOwnProperty('children')) {
      for (var i = 0; i < data.children.length; i++) {
        this.encodeIcon(data.children[i]);
      }
    }

    if (data.hasOwnProperty('pens')) {
      for (var i = 0; i < data.pens.length; i++) {
        this.encodeIcon(data.pens[i]);
      }
    }
  }

  async save(tip = true) {
    //alert('save');
    this.data = Object.assign({}, (window as any).topology.pureData());
    if (!this.data.name) {
      this.data.name = `topology.${new Date().toLocaleString()}`;
    }

    this.encodeIcon(this.data);

    var msg = {};
    this.$set(msg, 'web_msg_type', 2);
    this.$set(msg, 'page_id', this.$route.query.id);
    this.$set(msg, 'data', this.data);

    this.publishMsg('scada-web-req', JSON.stringify(msg));
  }

  async addImageUrl(params: any) {
    const ret: any = await axios.post('/api/save/image', params);
    if (ret.error) {
      return false;
    }

    this.getMaterials();
  }

  async deleteImage(params: any) {
    const ret: any = await axios.post('/api/delete/image', params);
    if (ret.error) {
      return false;
    }

    this.getMaterials();
  }

  async uploadFunc(detail: any) {
    //console.log(detail);
    const form = new FormData();
    form.append('file', detail.file);
    const ret: any = await axios.post('/api/save/image', form);
    if (ret.data.error) {
      return null;
    }

    console.log(ret.data.url);
    return ret.data.url;
  }

  onEvent(e: { name: string; params: any }) {
    console.log('onEvent', e);
    switch (e.name) {
      case 'save':
        this.save();
        break;
      case 'logout':
        // 退出登录
        this.user = null;
        // Do sth.
        break;
      case 'openMaterialGroup':
        // 展开/折叠图标工具栏分组
        console.log('openMaterialGroup', e.params);
        // Do sth.
        break;
      case 'addMaterial':
        // 添加“我的组件”
        // Do sth. For example:
        this.$router.push({
          path: '/',
          query: { component: '1' },
        });
        break;
      case 'editMaterial':
        // 编辑“我的组件”
        // Do sth. For example:
        this.$router.push({
          path: '/',
          query: { id: e.params.id, component: '1' },
        });
        break;
      case 'open':
        // 导航菜单configs.menus里面定义的action
        // 比如这里表示打开文件
        break;
      case 'addImageUrl':
        // 在“我的图片”里面添加了一张新图片
        //this.addImageUrl(e.params);
        break;
      case 'deleteImage':
        // 在“我的图片”里面删除了一张图片
        //this.deleteImage(e.params);
        break;
      case 'preview':
        // 点击工具栏“预览”

        // 保存当前编辑数据，方便预览时直接打开
        (window as any).topologyData = (window as any).topology.data;
        this.$router.push({
          path: '/preview',
          query: { id: this.$route.query.id, r: Date.now() + '' },
        });
        break;

      // ...
      // ...
    }
  }

  async getMaterials() {
    // alert('getMaterials');
    // 注册图形库
    this.materials.system = [];
    for (var i = 0; i < defalutMaterials.length; i++) {
      this.materials.system.push(defalutMaterials[i]);
    }
    // if (window.topologyTools) {
    //   this.materials.system.push({
    //     name: '企业图形库',
    //     expand: false,
    //     show: true,
    //     list: window.topologyTools,
    //   });
    // }

    this.materials.system.push({
      iconUrl: '//at.alicdn.com/t/font_2366205_nnqrrnc9mta.css', // 替换成真实的地址
      show: true,
      list: [], // 此处留空数组就好，会自动填充
    });

    this.materials.system.push({
      iconUrl: '/font/font_2052340_u3ww8v9eb5j/iconfont.css', // 替换成真实的地址
      show: true,
      list: [], // 此处留空数组就好，会自动填充
    });

    this.materials.system.push({
      iconUrl: '/font/font_2073009_ctn7qgh8t/iconfont.css', // 替换成真实的地址
      show: true,
      list: [], // 此处留空数组就好，会自动填充
    });

    this.materials.system.push({
      iconUrl: '/font/font_2073009_u56zfo0voi/iconfont.css', // 替换成真实的地址
      show: true,
      list: [], // 此处留空数组就好，会自动填充
    });

    // 国家电网图元规范
    this.materials.system.push({
      iconUrl: '/font/font_2395018_pl6jy69tbjr/iconfont.css', // 替换成真实的地址
      show: true,
      list: [], // 此处留空数组就好，会自动填充
    });

    let res: any = await axios.get('/images');
    console.log(res);
    this.materials.system.push(
      ...res.data.map((item: any) => {
        return {
          name: item.name, // 目录名
          list: item.list.map((ele: any) => {
            return {
              name: ele.name, // hover item 名
              image: ele.url, // 预览图以及拖出来的效果图
            };
          }),
          show: true,
          expand: false,
        };
      })
    );

    this.registerBuiness();

    this.materials = Object.assign({}, this.materials);
  }

  async initMqtt() {
    /*
  var options = {
    keepAlive: // 心跳时间 默认60s, 设置0为禁用
    username: // 用户名
    password: // 用户密码
    protocol: // 指定协议默认为ws(websocket) wss这是加密的websocket, 和http与https的差别差不多, 还有ssl, tcp...
    clientId: // 客户端id 唯一标识你的客户端的身份
    clean: // boolean  设置为 false 以在离线时接收 QoS 1 和 2 消息；
    reconnectionProid: //设置多长时间进行重新连接 单位毫秒
    connectionTimeout: // 设置超时时间
    protocolID: ‘ MQIsdp’// 和下面的参数指定mqtt的版本 5的最新的, 3
    protocolVersion: 3 
    reconnection: // boolean 断开是否需要再次连接 不传默认为true
    will: {
      ... // 这里面配置的连接强制断开
    }
  }
  */

    var willMsg = { id: this.$route.query.id, web_msg_type: 5 };
    var options = {
      //mqtt客户端的id，这里面应该还可以加上其他参数，具体看官方文档
      clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
      will: {
        topic: 'scada-web-req',
        payload: JSON.stringify(willMsg),
        retain: false,
        qos: <QoS>0,
      }, //{'id':this.$route.query.id, 'web_msg_type':5}
    };

    this.mqttClient = Mqtt.connect(globalParam.theMQTTConnect, options); // you add a ws:// url here
    this.mqttClient.on('connect', this.onMqttConnect);
    this.mqttClient.on('error', this.onMqttErr);
    this.mqttClient.on('message', this.onMqttMsg);
  }

  onMqttConnect() {
    this.mqttClient.subscribe('scada-web-rsp', this.OnMqttSubscribe);
  }

  OnMqttSubscribe(err: any) {
    var msg = {};
    this.$set(msg, 'web_msg_type', 1);
    this.$set(msg, 'page_id', this.$route.query.id);

    if (!err) {
      this.publishMsg('scada-web-req', JSON.stringify(msg));
    } else {
      //打印错误
      console.log(err);
    }
  }

  publishMsg(topic: string, msg: string) {
    console.log(topic + ':' + msg);
    this.mqttClient.publish(topic, msg); //'scada-web-req'
  }

  onMqttErr(err: any) {
    console.log(err);
    this.mqttClient.end();
  }

  onMqttMsg(topic: any, message: any) {
    console.log('topic[' + topic + ']-> ' + message.toString());
    var msg = JSON.parse(message);
    switch (msg.web_msg_type) {
      case 1:
        {
          // 读回页面page
          window.document.title = '组态配置--<' + msg.title + '>';
          this.decodeIcon(msg.data);
          this.data = msg.data;
          (window as any).topology.data = msg.data;
          (window as any).topology.render();

          (window as any).topology.data.socketEvent = true;
          (window as any).topology.on('mqtt', this.onMqttMessage);
          (window as any).topology.on('node', this.onNodeMessage);

          setTimeout(() => {
            var req = {};
            this.$set(req, 'web_msg_type', 3);

            this.publishMsg('scada-web-req', JSON.stringify(req));
          }, 500);
        }
        break;
      case 2:
        {
          // 保存页面page
          if ((msg.page_id = this.$route.query.id)) {
            this.$message.success('保存成功！');
          }
        }
        break;
      case 3:
      case 4:
        {
          // 读回全数据
          var msgData = msg.data;
          for (let i = 0; i < msgData.length; i++) {
            let id = msgData[i]['id'];
            let type = msgData[i]['type'];
            let pens = (window as any).topology.find(id, true, true);
            if (pens != null) {
              for (let j = 0; j < pens.length; j++) {
                let pen = pens[j];
                let penData = pen.data;
                switch (type) {
                  case 'yx':
                    {
                      // 不显示值, 只显示颜色
                      if (msgData[i]['value'] == 0) {
                        pen.fontColor = 'green';
                      } else {
                        pen.fontColor = 'red';
                      }
                    }
                    break;
                  case 'yc':
                    {
                      pen.text = msgData[i]['value'].toString();

                      switch (msgData[i]['alarm']) {
                        case 0:
                          {
                            pen.fontColor = 'green';
                            pen.textBackground = '';
                          }
                          break;
                        case 1:
                        case 4:
                          {
                            pen.fontColor = 'yellow';
                            pen.textBackground = 'red';
                          }
                          break;
                        case 2:
                        case 3:
                          {
                            pen.fontColor = 'green';
                            pen.textBackground = 'yellow';
                          }
                          break;
                      }
                    }
                    break;
                  case 'ym':
                    {
                      pen.text = msgData[i]['value'].toString();
                      pen.fontColor = 'green';
                    }
                    break;
                  case 'yk':
                    {
                      if (msg.web_msg_type === 3) {
                        let ctlData = {};
                        this.$set(ctlData, 'ctrl_id', id);
                        this.$set(ctlData, 'ctrl_type', 0);
                        this.$set(ctlData, 'gw_sn', msgData[i]['gw_sn']);
                        this.$set(ctlData, 'name', msgData[i]['name']);

                        if (penData == null) {
                          pen.data = [];
                          pen.data.push(ctlData);
                        } else {
                          penData.splice(0, 1, ctlData);
                        }
                      }

                      if (msgData[i]['value'] == 0) {
                        pen.fontColor = 'green';
                      } else {
                        pen.fontColor = 'red';
                      }
                    }
                    break;
                  case 'yt':
                    {
                      if (msg.web_msg_type === 3) {
                        let ctlData = {};
                        this.$set(ctlData, 'ctrl_id', id);
                        this.$set(ctlData, 'ctrl_type', 1);
                        this.$set(ctlData, 'gw_sn', msgData[i]['gw_sn']);
                        this.$set(ctlData, 'name', msgData[i]['name']);
                        
                        if (penData == null) {
                          pen.data = [];
                          pen.data.push(ctlData);
                        } else {
                          penData.splice(0, 1, ctlData);
                        }
                      }

                      pen.text = msgData[i]['value'].toString();
                      pen.fontColor = 'green';
                    }
                    break;
                  case 'gw':
                  case 'term':
                    {
                      if (msgData[i]['online']) {
                        pen.lineWidth = 2;
                        pen.strokeStyle = '#BD10E0';
                        pen.lineDash[0] = 0;
                        pen.lineDash[1] = 0;
                      } else {
                        pen.lineWidth = 2;
                        pen.strokeStyle = 'gray';
                        pen.lineDash[0] = 2;
                        pen.lineDash[1] = 6;
                      }
                    }
                    break;
                }
              }
            }
          }
        }
        break;
      case 6:
        {
          // 遥控消息
          let uuid = msg.ctrl_uuid;
          if (this.ctrlMsg.hasOwnProperty(uuid)) {
            if (msg.ctrl_result === 0) {
              this.$message.success('操作成功');
            } else {
              let info = '操作失败：' + msg.error_msg;
              this.$message.error(info);
            }
          }
          this.removeCtrlMsg(uuid);
        }
        break;
    }
  }

  /*onMqttMessage 页面加载后，Topology本身mqtt消息的监听，目前已经不再使用Topology本身的mqtt */
  onMqttMessage = (e: any) => {
    console.log(e);
  };

  /*onNodeMessage 页面加载后，Topology本身节点点击消息的监听回调函数*/
  onNodeMessage = (pen: any) => {
    let penData = pen.data;
    if (penData != null) {
      if (penData.length > 0) {
        const ctlData = penData[0];
        switch (ctlData.ctrl_type) {
          case 0:
            {
              console.log(this.$refs);
              (this.$refs.yk as any).doYK(ctlData);
            }
            break;
          case 1:
            {
              console.log(this.$refs);
              (this.$refs.yt as any).doYT(ctlData);
            }
            break;
        }
      }
    }
  };

  S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  }

  guid() {
    return (
      this.S4() +
      this.S4() +
      '-' +
      this.S4() +
      '-' +
      this.S4() +
      '-' +
      this.S4() +
      '-' +
      this.S4() +
      this.S4() +
      this.S4()
    );
  }

  addCtrlMsg(uuid: string, msg: object) {
    console.log('addCtrlMsg:' + uuid + msg);
    this.$set(this.ctrlMsg, uuid, msg);
  }

  removeCtrlMsg(uuid: string) {
    this.$delete(this.ctrlMsg, uuid);
  }
}
</script>
<style lang="scss">
.home {
  height: 100vh;
}
</style>
